﻿#include "GraphicsView.h"
#include <QScrollBar>
#include <QMenu>
#include "ItemBase.h"
#include <QFileDialog>
#include <QAction>
#include <QLabel>
#include "GraphicsScene.h"
#include <QHBoxLayout>
#include <QThread>
#include <QPushButton>
#include <QWidgetAction>
#include "ImageItem.h"
#include "qmutex.h"

GraphicsView::GraphicsView(QWidget* parent) : QGraphicsView(parent)
{
    this->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);//解决拖动是背景图片残影
    setDragMode(QGraphicsView::ScrollHandDrag);
    drawBg();
    // 隐藏水平/竖直滚动条
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    this->setBackgroundBrush(Qt::gray);
    // 设置场景范围
    setSceneRect(INT_MIN / 2, INT_MIN / 2, INT_MAX, INT_MAX);
    // 反锯齿
    setRenderHints(QPainter::Antialiasing);

    scene = new GraphicsScene;
    this->setScene(scene);

    itemImg = new ImageItem;
    scene->addItem(itemImg);

    drawItem = new ItemDraw;
    addItem(drawItem);

    //显示灰度值
    lblGrayValue = new QLabel(this);
    lblGrayValue->setObjectName("lblGrayValue_X");
    lblGrayValue->setStyleSheet("color:rgb(200,255,200); background-color:rgba(50,50,50,160); "
                                "font: Microsoft YaHei;font-size: 15px;");
    lblGrayValue->setVisible(false);
    lblGrayValue->setFixedWidth(702);
    auto vLayout = new QVBoxLayout();
    this->setLayout(vLayout);
    auto fLayout = new QHBoxLayout();
    fLayout->setSpacing(0);
    fLayout->setContentsMargins(0, 0, 0, 0);
    fLayout->addWidget(lblGrayValue);
    fLayout->addStretch();
    vLayout->addStretch();
    vLayout->addLayout(fLayout);
    connect(itemImg, &ImageItem::sigRGBValue, this, [&](QString InfoVal) {
        lblGrayValue->setText(InfoVal);
    });

    //显示文本
    lblOtherMsg = new QLabel(this);
    lblOtherMsg->setObjectName("BlobValue");
    lblOtherMsg->setStyleSheet("color:rgb(200,255,200); background-color:rgba(50,50,50,160); "
                               "font: Microsoft YaHei;font-size: 15px;font-weight: bold;");
    lblOtherMsg->setVisible(false);
    lblOtherMsg->setFixedWidth(300);
    //显示区域
    QWidget* msgWidget = new QWidget(this);
    msgWidget->setFixedHeight(25);
    msgWidget->setGeometry(2, 2, 300, 25);
    msgWidget->setStyleSheet("background-color:rgba(0,0,0,0);");
    auto fMsgLayout = new QHBoxLayout(msgWidget);
    fMsgLayout->setSpacing(0);
    fMsgLayout->setContentsMargins(0, 0, 0, 0);
    fMsgLayout->addWidget(lblOtherMsg);
    fMsgLayout->addStretch();

    setType(false, false);
}

void GraphicsView::dispImage(const QImage& image)
{
    //加锁
    static QMutex mutex;
    QMutexLocker locker(&mutex);
    int width = mImg.width();
    int height = mImg.height();
    mImg = image;
    itemImg->setPixmap(QPixmap::fromImage(image));
    if(width != mImg.width() || height != mImg.height()){
        getFit();
    }
}

void GraphicsView::addRegionList(QVector<QVector<QPointF>>& list, QColor color)
{
    for(auto lst : list){
        drawItem->addRegion(lst);
    }
}
void GraphicsView::addXldList(QVector<QVector<QPointF>>& list, QColor color)
{
    for(auto lst : list){
        drawItem->addXld(lst);
    }
}

void GraphicsView::clearDraw()
{
    drawItem->clearAll();
}

void GraphicsView::addItem(ItemBase* item)
{
    item->scale = zoomValue;
    this->scene->addItem(item);
    itemList << item;
}

void GraphicsView::removeItem(ItemBase *item)
{
    itemList.removeOne(item);
    scene->removeItem(item);
}

void GraphicsView::removeSelected()
{
    auto lstItem = scene->selectedItems();
    for(auto item : lstItem){
        scene->removeItem(item);
    }
}

//设定信息模块是否显示
void GraphicsView::setType(bool InfoFlg, bool lblGrayValueFlg)
{
    itemImg->setAcceptHoverEvents(!InfoFlg);
    lblGrayValue->setVisible(!lblGrayValueFlg);
}

void GraphicsView::showMsg(const QString &msg)
{
    lblOtherMsg->setText(msg);
}

void GraphicsView::clearItem()
{
    for(auto item : itemList){
        scene->removeItem(item);
    }
    itemList.clear();
}

ItemBase* GraphicsView::getSelectItem()
{
    auto lstItem = scene->selectedItems();
    if(lstItem.size() > 0){
        return static_cast<ItemBase*>(lstItem.at(0));
    } else {
        return nullptr;
    }
}

void GraphicsView::setToFit(qreal val)
{
    zoomFrame(val / zoomValue);
    zoomValue = val;
    this->horizontalScrollBar()->setSliderPosition(pixX);
    this->verticalScrollBar()->setSliderPosition(pixY);
}

void GraphicsView::zoomFrame(double value)
{
    this->scale(value, value);
    for(auto item : itemList){
        item->scale = zoomValue;
    }
    drawItem->scale = zoomValue;
}

void GraphicsView::getFit()
{
    if (this->width() < 1 || mImg.width() < 1){
        return;
    }
    //图片自适应方法
    double winWidth = this->width();
    double winHeight = this->height();
    double ScaleWidth = (mImg.width() + 1) / winWidth;
    double ScaleHeight = (mImg.height() + 1) / winHeight;
    double row1, column1;
    double s = 0;
    if (ScaleWidth >= ScaleHeight){
        row1 = -(1) * ((winHeight * ScaleWidth) - mImg.height()) / 2;
        column1 = 0;
        s = 1 / ScaleWidth;
    }else{
        row1 = 0;
        column1 = -(1.0) * ((winWidth * ScaleHeight) - mImg.width()) / 2;
        s = 1 / ScaleHeight;
    }
    if (zoomFit != s || pixX != column1 * s){
        zoomFit = s;
        pixX = column1 * s;
        pixY = row1 * s;
        setToFit(s);
    }
}

void GraphicsView::drawBg()
{
    bgPix.fill(color1);
    QPainter painter(&bgPix);
    painter.fillRect(0, 0, 18, 18, color2);
    painter.fillRect(18, 18, 18, 18, color2);
    painter.end();
}

void GraphicsView::mousePressEvent(QMouseEvent* event)
{
    if(event->button() == Qt::RightButton){
        setToFit(zoomFit);
    }
    QGraphicsView::mousePressEvent(event);
}

void GraphicsView::resizeEvent(QResizeEvent* event)
{
    getFit();
    QGraphicsView::resizeEvent(event);
}

void GraphicsView::mouseReleaseEvent(QMouseEvent* event)
{
    QGraphicsView::mouseReleaseEvent(event);
}

void GraphicsView::mouseDoubleClickEvent(QMouseEvent* event)
{
    setToFit(zoomFit);
    QGraphicsView::mouseDoubleClickEvent(event);
}

void GraphicsView::mouseMoveEvent(QMouseEvent* event)
{
    QGraphicsView::mouseMoveEvent(event);
}

void GraphicsView::wheelEvent(QWheelEvent* event)
{
#if QT_VERSION >= 0x060000
    // Qt 6 的代码
    if ((event->angleDelta().y() > 0) && (zoomValue >= 50)) //最大放大到原始图像的50倍
        return;
    else if ((event->angleDelta().y() < 0) && (zoomValue <= 0.02))
        return;
    else{
        //鼠标滚轮向前滚动
        if (event->angleDelta().y() > 0){
            zoomValue *= 1.1; //每次放大10%
            zoomFrame(1.1);
        }else{
            zoomFrame(0.9);
            zoomValue *= 0.9; //每次缩小10%
        }
    }
#else
    // Qt 5 的代码
    if ((event->delta() > 0) && (zoomValue >= 50)) //最大放大到原始图像的50倍
        return;
    else if ((event->delta() < 0) && (zoomValue <= 0.02))
        return;
    else{
        //鼠标滚轮向前滚动
        if (event->delta() > 0){
            zoomValue *= 1.1; //每次放大10%
            zoomFrame(1.1);
        }else{
            zoomFrame(0.9);
            zoomValue *= 0.9; //每次缩小10%
        }
    }
#endif

}

void GraphicsView::drawBackground(QPainter* painter, const QRectF& rect)
{
    Q_UNUSED(rect);
    painter->drawPixmap(QPoint(), QPixmap::fromImage(mImg));
}

void GraphicsView::paintEvent(QPaintEvent* event)
{
    QPainter paint(this->viewport());
    paint.drawTiledPixmap(QRect(QPoint(0, 0), QPoint(this->width(), this->height())), bgPix);  //绘制背景
    QGraphicsView::paintEvent(event);
}

//右键菜单
void GraphicsView::contextMenuEvent(QContextMenuEvent* event)
{
    QPoint pos = event->pos();
    pos = this->mapToGlobal(pos);
    QMenu* menu = new QMenu(this);
    //菜单样式
    QString menuStyle(
        "QMenu::item{"
        "color: rgb(0, 0, 0);"
        "}"
        "QMenu::item:hover{"
        "background-color: rgb(176, 190, 225);"
        "}"
        "QMenu::item:selected{"
        "background-color: rgb(176, 190, 225);"
        "}"
        );
    QString buttonStyle(
        "QPushButton{"
        "color: rgb(0, 0, 0);"
        "border: none;"
        "text-align: left;"
        "font: 9pt Microsoft YaHei;"
        "padding-left: 5px;"
        "padding-right: 5px;"
        "}"
        "QPushButton::hover{"
        "background-color: rgba(176, 190, 225, 200);"
        "}"
        "QPushButton::selected{"
        "background-color: rgba(176, 190, 255, 255);"
        "}"
        );
    menu->setStyleSheet(menuStyle);
    auto addRightButton = [&](const QString& btnTxt, void (GraphicsView::*func)()){
        QPushButton* btn = new QPushButton(menu);
        btn->setStyleSheet(buttonStyle);
        btn->setText(btnTxt);
        btn->setIconSize(QSize(23, 23));
        QWidgetAction* wgtAction = new QWidgetAction(this);
        wgtAction->setDefaultWidget(btn);
        connect(btn, &QPushButton::clicked, this, func);
        connect(btn, &QPushButton::clicked, menu, &QMenu::close);
        menu->addAction(wgtAction);
    };
    // addRightButton("放大", &GraphicsView::onZoomInImage);
    // menu->addSeparator();
    // addRightButton("缩小", &GraphicsView::onZoomOutImage);
    // menu->addSeparator();
    addRightButton("自适应图像", &GraphicsView::onFitImage);
}

void GraphicsView::onZoomInImage()
{
    double tmp_buf = zoomValue;
    tmp_buf *= 1.1;
    double tmp = tmp_buf / zoomValue;
    zoomValue *= tmp;
    zoomFrame(tmp);
}

void GraphicsView::onZoomOutImage()
{
    double tmp_buf = zoomValue;
    tmp_buf *= 0.9;
    double tmp = tmp_buf / zoomValue;
    zoomValue *= tmp;
    zoomFrame(tmp);
}

void GraphicsView::onFitImage()
{
    setToFit(zoomFit);
}
